/******************************************************************************

  File Name     : image_container.cpp
  Version       : Initial Draft
  Author        : tongzhilin
  Created       : 2020/8/6
  Last Modified :
  Description   : image_container
  Function List :
  History       :
  1.Date        : 2020/8/6
    Author      : tongzhilin
    Modification: Created file

******************************************************************************/
#include "image_container.h"
#include "mp_allocator.h"
#include "mp_common.h"
#include "mp_mat.h"
#ifdef INFERENCE_NNIE
    #include "hi_utils.h"
#endif

ALG_IMAGE_S cv2alg(cv::Mat& _stCvImage, INT32 _s32Alignment)
{
    MP_ASSERT(_s32Alignment == 1 || _s32Alignment == 4 || _s32Alignment == 8 ||
              _s32Alignment == 16 || _s32Alignment == 32 || _s32Alignment == 64);
    INT32 C = _stCvImage.type() == CV_8UC1 ? 1 : 3;
    INT32 W = _stCvImage.cols;
    INT32 H = _stCvImage.rows;
    INT32 S = aligned(W, _s32Alignment);
    INT32 size = H * S * C;

    ALG_IMAGE_S stAlgImage;

#ifdef INFERENCE_NNIE
    MP_CHECK(HI_MPI_SYS_MmzAlloc_Cached(&stAlgImage.au64PhyAddr[0],(void **)&stAlgImage.au64VirAddr[0],
        nullptr, nullptr, size));
#else
    stAlgImage.au64VirAddr[0] = (UINT64)(void*)malloc(size);
    MP_ASSERT(stAlgImage.au64VirAddr[0]);
    stAlgImage.au64PhyAddr[0] = stAlgImage.au64VirAddr[0];
#endif

    stAlgImage.u32Width = W;
    stAlgImage.u32Height = H;
    stAlgImage.enType = C == 3 ? ALG_IMAGE_TYPE_U8C3_PLANAR : ALG_IMAGE_TYPE_U8C1;
    for (INT32 c = 0; c < C; ++c)
    {
        stAlgImage.au32Stride[c] = S;
    }
    for (INT32 c = 1; c < C; ++c)
    {
        stAlgImage.au64PhyAddr[c] = stAlgImage.au64PhyAddr[0] + c * H * S;
        stAlgImage.au64VirAddr[c] = stAlgImage.au64VirAddr[0] + c * H * S;
    }

    // hwc to chw
    // (BGR BGR BGR) -> (BBB GGG RRR)
    uint8_t* __restrict pstAlgImagePtr = (uint8_t*)stAlgImage.au64VirAddr[0];
    uint8_t* __restrict pstCvImagePtr = _stCvImage.ptr();
    for (INT32 c = 0; c < C; ++c)
    for (INT32 h = 0; h < H; ++h)
    for (INT32 w = 0; w < W; ++w)
    {
        pstAlgImagePtr[c * H * S + h * S + w] = pstCvImagePtr[h * W * C + w * C + c];
    }

#ifdef INFERENCE_NNIE
    MP_CHECK(HI_MPI_SYS_MmzFlushCache(stAlgImage.au64PhyAddr[0], (void*)stAlgImage.au64VirAddr[0], size));
#endif
    return stAlgImage;
}

